package yslog

import (
	"context"
	"fmt"
	"gitee.com/kmyss/gf-ex/ysansi"
	"github.com/gogf/gf/v2/os/gproc"
	"io"
	"os"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gcmd"
	"github.com/gogf/gf/v2/os/glog"
)

const (
	ysLogConfigName = "yslog"
	ErrorHead       = "[Error] "
	DebugHead       = "[Debug] "
	WarningHead     = "[Warning] "
)

var (
	logger    *glog.Logger
	isVerbose bool
)

func initLog() {
	if logger = Log(ysLogConfigName); logger == nil {
		logger = glog.New()
	}
	logger.SetStack(false)
	logger.SetDebug(false)
	logger.SetHeaderPrint(false)

	if gcmd.GetOpt("debug") != nil {
		logger.SetDebug(true)
	}

	if gcmd.GetOpt("verbose") != nil {
		isVerbose = true
	}
}

func getLogger() *glog.Logger {
	if logger == nil {
		initLog()
	}
	return logger
}

func Print(v ...interface{}) {
	getLogger().Print(context.TODO(), v...)
}

func PrintToFile(v ...interface{}) {
	l := getLogger().Clone()
	l.Stdout(false).Print(context.TODO(), v...)
}

func Printf(format string, v ...interface{}) {
	getLogger().Printf(context.TODO(), format, v...)
}

func PrintV(v ...interface{}) {
	if isVerbose {
		Print(v...)
	}
}

func PrintVf(format string, v ...interface{}) {
	if isVerbose {
		Printf(format, v...)
	}
}

func PrintfToFile(format string, v ...interface{}) {
	getLogger().Stdout(false).Printf(context.TODO(), format, v...)
}

func warningP(str string) {
	getLogger().Warning(context.TODO(), str)
}

func Warning(v ...interface{}) {
	str := fmt.Sprint(append(g.Slice{ysansi.LightYellowStr(WarningHead)}, v...)...)
	warningP(str)
}

func Warningf(format string, v ...interface{}) {
	str := fmt.Sprintf(ysansi.LightYellowStr(WarningHead)+format, v...)
	warningP(str)
}

func WarningV(v ...interface{}) {
	if isVerbose {
		Warning(v...)
	}
}

func WarningVf(format string, v ...interface{}) {
	if isVerbose {
		Warningf(format, v...)
	}
}

func errorP(str string) {
	getLogger().Error(context.TODO(), str)
}

func Error(v ...interface{}) {

	str := fmt.Sprint(append(g.Slice{ysansi.RedStr(ErrorHead)}, v...)...)
	errorP(str)
}

func Errorf(format string, v ...interface{}) {
	str := fmt.Sprintf(ysansi.RedStr(ErrorHead)+format, v...)
	errorP(str)
}

func ErrorV(v ...interface{}) {
	if isVerbose {
		Error(v...)
	}
}

func ErrorVf(format string, v ...interface{}) {
	if isVerbose {
		Errorf(format, v...)
	}
}

func fatalP(str string) {
	getLogger().Fatal(context.TODO(), str)
}

func Fatal(v ...interface{}) {
	str := fmt.Sprint(append(g.Slice{ysansi.LightRedStr(ErrorHead)}, v...)...)
	fatalP(str)
}

func Fatalf(format string, v ...interface{}) {
	str := fmt.Sprintf(ysansi.LightRedStr(ErrorHead)+format, v...)
	fatalP(str)
}

func FatalV(v ...interface{}) {
	if isVerbose {
		Fatal(v...)
	}
}

func FatalVf(format string, v ...interface{}) {
	if isVerbose {
		Fatalf(format, v...)
	}
}

func debugP(str string) {
	getLogger().Debug(context.TODO(), str)
}

func Debug(v ...interface{}) {
	str := fmt.Sprint(append(g.Slice{ysansi.LightYellowStr(DebugHead)}, v...)...)
	debugP(str)
}

func Debugf(format string, v ...interface{}) {
	str := fmt.Sprintf(ysansi.YellowStr(DebugHead)+format, v...)
	debugP(str)
}

func DebugV(v ...interface{}) {
	if isVerbose {
		Debug(v...)
	}
}

func DebugVf(format string, v ...interface{}) {
	if isVerbose {
		Debugf(format, v...)
	}
}

func Dump(v ...interface{}) {
	g.Dump(v...)
}

func DumpV(v ...interface{}) {
	if isVerbose {
		Dump(v...)
	}
}

func GetWriter() io.Writer {
	return getLogger()
}

func ShellRun(ctx context.Context, cmd string) error {
	return gproc.Shell(ctx, cmd, GetWriter(), os.Stdin)
}
